module factories.game;

/// 初始化游戏，返回下一个待初始化的变量首地址，返回null表示初始化完成
extern (C) export void* initGame(int seed) {
	import factories.factory;
	import factories.storage;
	import factories.map;
	import factories.util;

	static i = 0;

	if (i == 0) {
		factories.util.seed = seed;
		initMap();
		initStorage();
	}
	foreach (j, ref T; Data) {
		if (i == j) {
			i++;
			return &T;
		}
	}
	net.build();
	return null;
}

/// 常量表
extern (C) export immutable Color[256][8] constants = [
	// 植被&土壤类型
	getParam(),
	// 1水体
	initColorsMap(Color(0, 0, 128), Color(0, 80, 100), Color(0, 45, 85), Color(0, 113, 97)),
	// 2苔原/草地/湿地
	initColorsMap(Color(141, 198, 166), Color(210, 201, 93), Color(141, 198, 166), Color(79, 225, 56)),
	// 3针叶林
	initColorsMap(Color(96, 161, 150), Color(129, 174, 42), Color(96, 161, 150), Color(1, 191, 53)),
	// 4落叶阔叶林
	initColorsMap(Color(96, 161, 96), Color(174, 109, 42), Color(96, 161, 96), Color(107, 191, 1)),
	// 5常绿阔叶林
	initColorsMap(Color(96, 161, 123), Color(174, 164, 42), Color(96, 161, 123), Color(30, 191, 1)),
	// 6常绿硬叶林
	initColorsMap(Color(146, 191, 176), Color(160, 191, 176), Color(146, 191, 166), Color(150, 201, 141)),
	// 7雨林
	initColorsMap(Color(96, 161, 123), Color(174, 164, 42), Color(96, 161, 123), Color(30, 191, 1)),
];

/// 颜色
struct Color {
	ubyte r, g, b;
}

Color mix(Color a, Color b, float f) =>
	Color(cast(ubyte)(a.r + (b.r - a.r) * f),
		cast(ubyte)(a.g + (b.g - a.g) * f),
		cast(ubyte)(a.b + (b.b - a.b) * f));

Color[256] initColorsMap(Color th11, Color th21, Color th12, Color th22) {
	import factories.util;

	Color[256] map;
	for (int i; i < 16; i++) {
		for (int j; j < 16; j++) {
			const dx = saturate(i / 8.);
			const c = mix(th11, th21, dx);
			const c2 = mix(th12, th22, dx);
			const dy = saturate((j - 4) / 10.);
			map[i << 4 | j] = mix(c, c2, dy);
		}
	}
	return map;
}
/++
R:植被类型
| 字段           | 中文       | 说明                  |
| -------------- | ---------- | --------------------- |
| tundra         | 苔原       | 2<温度<=4，湿度>7       |
| steppe         | 草原       | 4<温度<=7，4<湿度<=7  |
| marsh          | 湿地       | 温度>7，湿度>13       |
| coniferous     | 针叶林     | 4<温度<=7，湿度>7     |
| deciduous      | 落叶阔叶林 | 7<温度<=9，7<=湿度<13     |
| evergreen      | 常绿阔叶林 | 9<温度<=11，湿度>7    |
| sclerophyllous | 常绿硬叶林 | 11<温度<=13，4<湿度<=7 |
| forest         | 雨林       | 温度>13，11<=湿度<13  |
G:土壤类型
| 字段     | 中文 | 说明                 |
| -------- | ---- | -------------------- |
| none     | 裸地 | 其他条件             |
| sandy    | 沙土 | 2<温度<=7，4<湿度<=7 |
| drab     | 褐土 | 温度>7，4<湿度<=7       |
| laterite | 红土 | 温度>7，湿度>7       |
| loess    | 黄土 | 2<温度<=7，7<湿度<=11 |
| black    | 黑土 | 2<温度<=7，湿度>11    |
B:贮藏方式
+/
Color[256] getParam() {
	import factories.generated;

	Color[256] map;
	for (int i; i < 16; i++) {
		if (i & 1) { // 湿度为奇数才有植被
			for (int j; j < 16; j++) {
				Terrain t;
				if (j > 2 && j <= 4 && i > 7)
					t = Terrain.tundra;
				else if (j > 4 && j <= 7 && i > 4 && i <= 7)
					t = Terrain.steppe;
				else if (j > 7 && i > 13)
					t = Terrain.marsh;
				else if (j > 4 && j <= 7 && i > 7)
					t = Terrain.coniferous;
				else if (j > 7 && j <= 9 && i >= 7 && i < 13)
					t = Terrain.deciduous;
				else if (j > 9 && j <= 11 && i > 7)
					t = Terrain.evergreen;
				else if (j > 11 && j <= 13 && i > 4 && i <= 7)
					t = Terrain.sclerophyllous;
				else if (j > 13 && i >= 11 && i < 13)
					t = Terrain.forest;
				map[i << 4 | j].r = cast(ubyte)t;
			}
		}
		for (int j; j < 16; j++) {
			Soil s;
			if (j > 2 && j <= 4 && i > 7)
				s = Soil.sandy;
			else if (j > 4 && j <= 7 && i > 4 && i <= 7)
				s = Soil.drab;
			else if (j > 7 && i > 7)
				s = Soil.laterite;
			else if (j > 4 && j <= 7 && i > 7 && i <= 11)
				s = Soil.loess;
			else if (j > 4 && j <= 7 && i > 11)
				s = Soil.black;
			map[i << 4 | j].g = cast(ubyte)s;
		}
	}
	for (int i; i <= Items.max; i++) {
		StorageType s = StorageType.solid;
		switch (i) with (Items) {
		case water, coolant, LNG, crudeOil, oxyOrganics:
			s = StorageType.liquid;
			break;
		case hydrogen, hydrocarbon, ammonia:
			s = StorageType.gas;
			break;
		case superconductor:
			s = StorageType.cryogenic;
			break;
		case alkali, sulfuricAcid, nitricAcid:
			s = StorageType.corrosive;
			break;
		case fuelRod, radioactiveWaste:
			s = StorageType.radioactive;
			break;
		default:
		}
		map[i].b = cast(ubyte)s;
	}
	return map;
}
